package pub.pjoc.config.aop;

import pub.pjoc.cache.CacheService;
import pub.pjoc.cache.vo.Cache;
import pub.pjoc.config.ConfigReloadable;
import pub.pjoc.util.JacksonHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * Cache service for service.
 *
 * @author xiongyingqi
 * @since 16-11-29 下午6:32
 */
public class ServiceCollectionTypeCacheInterceptor<T> implements ConfigReloadable {
  private static final Logger logger = LoggerFactory.getLogger(ServiceCollectionTypeCacheInterceptor.class);
  private CacheService cacheService;
  private final String cacheGroup;
  private final Class<T> rawType;

  public ServiceCollectionTypeCacheInterceptor(Class<T> rawType, String cacheGroup) {
    this.rawType = rawType;
    this.cacheGroup = cacheGroup;
  }

  @SuppressWarnings("unchecked")
  public Collection<T> getCacheById(ProceedingJoinPoint call, String id)
      throws Throwable {
    String cacheValue = null;
    try {
      cacheValue = cacheService.getCacheValue(cacheGroup, id);
    } catch (Exception e) {
      logger.error("", e);
    }
    if (cacheValue != null) {
      try {
        List<T> found = JacksonHelper.convertJsonToListByRawType(cacheValue, rawType);
        if (logger.isDebugEnabled()) {
          logger.debug("Got cache: {}", found);
        }
        if (found != null) {
          return found;
        }
      } catch (IOException e) {
        logger.error("", e);
      }
    }

    Object proceed = call.proceed();
    if (proceed != null) {
      try {
        String jsonString = JacksonHelper.getJsonString(proceed);
        cacheService.setCache(new Cache(cacheGroup, id, jsonString));
        if (logger.isInfoEnabled()) {
          logger.info("Setting configs: {} to cache.", proceed);
        }
      } catch (Exception e) {
        logger.error("", e);
      }
      return (Collection<T>) proceed;
    } else {
      return null;
    }
  }

  public CacheService getCacheService() {
    return cacheService;
  }

  public void setCacheService(CacheService cacheService) {
    this.cacheService = cacheService;
  }

  @Override
  public boolean reloadConfig() {
    try {
      cacheService.clearCachesByGroup(cacheGroup);
    } catch (Exception e) {
      logger.error("", e);
      return false;
    }
    return true;
  }
}
